#ifndef E7854C6D_B4FC_46A5_9D11_3D10CC5CB817
#define E7854C6D_B4FC_46A5_9D11_3D10CC5CB817

#include <iostream>
#include <unistd.h>
#include "json.hpp"
#include <cctype>
#include <sys/types.h>
#include <sys/wait.h>
using json = nlohmann::json;

class CGI
{
public:
    CGI()
    {
        getRecvMessage_CGI();
        recv_mess = urlDecode(recv_mess); // 解码
    }
    ~CGI()
    {}
public:
    bool getRecvMessage_CGI()
    {
        bool result = false;
        std::string method = getenv("METHOD");
        if(method == "GET")
        {
            recv_mess = getenv("QUERY_STRING");
            std::cout << recv_mess << std::endl;
            result = true;
            std::cout << "GET 方法请求资源" << std::endl;
            #define ISGET 1
        }
        else if(method == "POST")   // 获取正文的多少个字节
        {   // 从 0 号文件描述符中获取
            int content_length = std::stoi(getenv("Content-Length"));
            char ch = 0;
            while (content_length)
            {
                read(0, &ch, 1);
                recv_mess.push_back(ch);
                content_length--;
            }
            result = true;
        }
        else
        {
            // TODO
        }
        return result;
    }
    // 如果 GET 方法切割字符串
    void cutString(std::string& target, std::string sep, std::string& out_left, std::string& out_right)
    {
        size_t pos = target.find(sep);
        if(pos != std::string::npos)
        {
            out_left = target.substr(0, pos);
            out_right = target.substr(pos+sep.size());
        }
    }
    // GET 方法字符串填充
    void getMethodStringHeader()
    {
        // 对获取的这些信息做出处理, eg:recv_mes: a=100&b=200
        std::string str_left, str_right;
        cutString(recv_mess, "&", str_left, str_right);
        cutString(str_left, "=", name1, value1);
        cutString(str_right, "=", name2, value2);
    }
    // 显示GET 方法的信息
    void showGetMessage() const
    {  
        // 3.debug,将信息发送到与 http 交互的匿名管道上（1号文件描述符）
        std::cout << name1 << " : " << value1 << std::endl;
        std::cout << name2 << " : " << value2 << std::endl;

        // 4.debug,将信息发送到终端上（2号文件描述符）
        std::cerr << name1 << " : " << value1 << std::endl;
        std::cerr << name2 << " : " << value2 << std::endl;
    }
    // POST 方法获取信息
    std::string postMethodMessage()
    {
        return recv_mess;
    }
    // Decode 解码
    std::string urlDecode(const std::string &str) {
        std::string result;
        for (size_t i = 0; i < str.size(); ++i) {
            if (str[i] == '%' && i + 2 < str.size()) {
                int hex1 = std::tolower(str[i + 1]);
                int hex2 = std::tolower(str[i + 2]);
                if (isxdigit(hex1) && isxdigit(hex2)) {
                    int value = (hex1 <= '9' ? hex1 - '0' : hex1 - 'a' + 10) * 16 +
                                (hex2 <= '9' ? hex2 - '0' : hex2 - 'a' + 10);
                    result += static_cast<char>(value);
                    i += 2;
                    continue;
                }
            }
            result += str[i];
        }
        return result;
    }
    // Json解析
    void jsonParse()
    {
        // 1. 解析 JSON 字符串
        std::cerr << "recv_mess: " << recv_mess << std::endl;
        auto pos = recv_mess.find("=");
        if(pos != std::string::npos)
        {
            recv_mess = recv_mess.substr(pos + 1); // 获取等号后面的内容
        }
        std::cerr << "Parsed message: " << recv_mess << std::endl;  // 输出: Parsed message: ls
    }
    std::string getRecvMessage() const
    {
        return recv_mess;
    }
private:
    std::string recv_mess;
public:
#ifdef ISGET
    std::string name1;
    std::string name2;
    std::string value1;
    std::string value2;
#elif
    std::string post_content;
#endif
};

class Com_Exe
{
    #define SEP " \t\n" 
    #define SIZE 1024
public:
    char* argv[12];
    std::string command;

    Com_Exe(const std::string& cmd)
    {
        command = cmd;
        Split((char*)command.c_str());
    }
public:
    char pwd[SIZE];
    char env[SIZE]; // for test
    int lastcode = 0;

    const char* HostName()
    {
        char *hostname = getenv("HOSTNAME");
        if(hostname) return hostname;
        else return "None";
    }

    const char* UserName()
    {
        char *hostname = getenv("USER");
        if(hostname) return hostname;
        else return "None";
    }

    const char *CurrentWorkDir()
    {
        char *hostname = getenv("PWD");
        if(hostname) return hostname;
        else return "None";
    }

    char *Home()
    {
        return getenv("HOME");
    }
public:
    // 字符串分割
    void Split(char in[])
    {
        int i = 0;
        argv[i++] = strtok(in, SEP); // "ls -a -l"
        while(argv[i++] = strtok(NULL, SEP)); // 故意将== 写成 =
    }
    void Execute()
    {
        pid_t id = fork();
        if(id == 0)
        {
            // 让子进程执行命名
            execvp(argv[0], argv);
            exit(1);
        }
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if(rid == id) lastcode = WEXITSTATUS(status); 
    }
    int BuildinCmd()
    {
        int ret = 0;
        // 1. 检测是否是内建命令, 是 1, 否 0
        if(strcmp("cd", argv[0]) == 0)
        {
            // 2. 执行
            ret = 1;
            char *target = argv[1]; //cd XXX or cd
            if(!target) target = Home();
            chdir(target);
            char temp[1024];
            getcwd(temp, 1024);
            snprintf(pwd, SIZE, "PWD=%s", temp);
            putenv(pwd);
        }
        else if(strcmp("export", argv[0]) == 0)
        {
            ret = 1;
            if(argv[1])
            {
                strcpy(env, argv[1]);
                putenv(env);
            }
        }
        else if(strcmp("echo", argv[0]) == 0)
        {
            ret = 1;
            if(argv[1] == NULL) {
                printf("\n");
            }
            else{
                if(argv[1][0] == '$')
                {
                    if(argv[1][1] == '?')
                    {
                        printf("%d\n", lastcode);
                        lastcode = 0;
                    }
                    else{
                        char *e = getenv(argv[1]+1);
                        if(e) printf("%s\n", e);
                    }
                }
                else{
                    printf("%s\n", argv[1]);
                }
            }
        }
        return ret;
    }
};



#endif /* E7854C6D_B4FC_46A5_9D11_3D10CC5CB817 */
